// 自定义协议
#pragma once

#include <iostream>
#include <string>
#include <cstring>
#include <jsoncpp/json/json.h>
#include <sys/types.h>
#include <sys/socket.h>

namespace ns_protocol
{

// #define MYSELF 1
#define SPACE " "
#define SPACE_LEN strlen(SPACE)

#define SEP "\r\n"
#define SEP_LEN strlen(SEP)

    class Request
    {
    public:
        // 序列化

        // 1、自主实现 "length\r\n_x _op _y\r\n" 的格式  \r\n:区分长度和有效数据
        //"length\r\n_x _op _y\r\nlength\r\n_x _op _y\r\n" :第二次读又会从length开始读
        // 2、使用现成的方案
        std::string Serialize()
        {
#ifdef MYSELF
            std::string str;
            str = std::to_string(_x);
            str += SPACE;
            str += _op;
            str += SPACE;
            str += std::to_string(_y);

            return str;
#else
            Json::Value root;
            root["x"] = _x;
            root["y"] = _y;
            root["op"] = _op;
            Json::FastWriter writer;
            return writer.write(root);
#endif
        }
        // 反序列化
        bool Deserialize(const std::string &str)
        {
#ifdef MYSELF
            std::size_t left = str.find(SPACE);
            if (left == std::string::npos)
                return false;
            std::size_t right = str.find(SPACE);
            if (right == std::string::npos)
                return false;
            _x = atoi(str.substr(0, left).c_str());
            _y = atoi(str.substr(right + SPACE_LEN).c_str());
            if (left + SPACE_LEN > str.size())
                _op = str[left + SPACE_LEN];
                //_op = (const char)str.substr(left + SPACE_LEN, right).c_str();

#else
            Json::Value root;
            Json::Reader reader;
            reader.parse(str, root);
            _x = root["x"].asInt();
            _y = root["y"].asInt();
            _op = root["op"].asInt();

            return true;

#endif
        }

    public:
        Request() {}
        Request(int x, int y, char op)
            : _x(x), _y(y), _op(op)
        {
        }

        ~Request() {}

    public:
        int _x;
        int _y;
        char _op; //  + - * / %
    };

    ///////////////////////////////////////////////////

    class Response
    {
    public:
        // 序列化
        std::string Serialize()
        {
#ifdef MYSELF
            std::string s;
            s = std::to_string(_code);
            s += SPACE;
            s += std::to_string(_result);

            return s;
#else
            Json::Value root;
            root["code"] = _code;
            root["result"] = _result;
            Json::FastWriter writer;
            return writer.write(root);
#endif
        }
        // 反序列化
        bool Deserialize(const std::string &s)
        {
#ifdef MYSELF
            std::size_t pos = s.find(SPACE);
            if (pos == std::string::npos)
                return false;
            _code = atoi(s.substr(0, pos).c_str());
            _result = atoi(s.substr(pos + SPACE_LEN).c_str());
            return true;
#else
            Json::Value root;
            Json::Reader reader;
            reader.parse(s, root);
            _code = root["code"].asInt();
            _result = root["result"].asInt();

            return true;
#endif
        }

    public:
        Response() {}
        Response(int result, int code)
            : _result(result), _code(code) {}
        ~Response() {}

    public:
        int _result;
        int _code; // 计算结果状态码
        // code的目的：返回计算异常状态，如 %0、/0 等
    };

    bool Recv(int sock, std::string *out)
    {
        char buff[1024];
        // recv怎么保证读到的inbuff是一个完整的请求
        // "1234 + 5678": 1234 +
        // "1234 + 5678": 1234 + 5678 123+99
        // "1234"
        // 必须是："1234 + 5678"，单纯的recv是无法解决的，需要重新定制协议

        ssize_t s = recv(sock, buff, sizeof(buff) - 1, 0);
        if (s > 0)
        {
            buff[s] = 0;
            *out += buff;
        }
        else if (s == 0)
        {
            std::cout << "client quit" << std::endl;
            return false;
        }
        else
        {
            std::cout << "recv error" << std::endl;
            return false;
        }
        return true;
    }

    void Send(int sock, const std::string str)
    {
        int n = send(sock, str.c_str(), str.size(), 0);
        if (n < 0)
            std::cout << "send error" << std::endl;
    }

    //"length\r\n_x _op _y\r\n"
    std::string Decode(std::string &buff) // 报文完整解析
    {
        std::size_t pos = buff.find(SEP);
        if (pos == std::string::npos)
            return ""; // 相当于不做处理

        int size = atoi(buff.substr(0, pos).c_str());
        int surplus = buff.size() - pos - 2 * SEP_LEN; // 读到的内容长度

        if (surplus >= size) // 至少有一个合法报文
        {
            buff.erase(0, pos + SEP_LEN);
            std::string s = buff.substr(0, size);
            buff.erase(0, size + SEP_LEN); // 去掉正文 + \r\n
        }
        else
            return "";
    }

    //"12\r\nXXXXXX\r\n"
    std::string Encode(std::string &s) // 加报头
    {
        std::string length = std::to_string(s.size());
        std::string new_package = length;
        new_package += SEP;
        new_package += s;
        new_package += SEP;
        return new_package;
    }

}
